<template>
  <div :class="prefixCls" class="relative h-[100%] lt-md:px-10px lt-sm:px-10px lt-xl:px-10px">
    <div class="relative mx-auto h-full flex">
      <div
        :class="`${prefixCls}__left flex-1 bg-gray-500 bg-opacity-20 relative p-30px lt-xl:hidden overflow-x-hidden overflow-y-auto`"
      >
        <!-- 左上角的 logo、系统标题 -->
        <div class="relative flex items-center text-white">
          <img alt="" class="mr-10px h-48px w-48px" src="@/assets/imgs/logo.png" />
          <span class="text-20px font-bold">{{ appStore.getTitle }}</span>
        </div>
        <!-- 左边的背景图、欢迎语 -->
        <div class="h-[calc(100%-60px)] flex items-center justify-center">
          <TransitionGroup
            appear
            enter-active-class="animate__animated animate__bounceInLeft"
            tag="div"
          >
            <img key="1" src="@/assets/svgs/login-box-bg.svg" alt="" />
            <div key="2" class="text-3xl text-white">{{ t('login.welcome') }}</div>
            <div key="3" class="mt-5 text-14px font-normal text-white"
              >{{ t('login.message') }}
            </div>
          </TransitionGroup>
        </div>
      </div>
      <div
        class="relative flex-1 p-30px dark:bg-[var(--login-bg-color)] lt-sm:p-10px overflow-x-hidden overflow-y-auto"
      >
        <!-- 右上角的主题、语言选项 -->
        <div
          class="flex items-center justify-between at-2xl:justify-end at-xl:justify-end color-[var(--el-text-color-primary)]"
        >
          <div class="flex items-center at-2xl:hidden at-xl:hidden">
            <img alt="" class="mr-10px h-48px w-48px" src="@/assets/imgs/logo.png" />
            <span class="text-20px font-bold">{{ appStore.getTitle }}</span>
          </div>
          <div class="flex items-center justify-end space-x-10px h-48px">
            <ThemeSwitch />
            <LocaleDropdown />
          </div>
        </div>
        <!-- 右边的登录界面 -->
        <Transition appear enter-active-class="animate__animated animate__bounceInRight">
          <div
            class="m-auto h-[calc(100%-60px)] w-[100%] flex items-center at-2xl:max-w-500px at-lg:max-w-500px at-md:max-w-500px at-xl:max-w-500px"
          >
            <ElForm
              v-show="getShow"
              ref="loginFormRef"
              :model="loginData.loginForm"
              :rules="loginRules"
              :disabled="loginDisabled"
              class="login-form"
              label-position="top"
              label-width="120px"
              size="large"
            >
              <el-row class="mx-[-10px]">
                <el-col :span="24" class="px-10px">
                  <el-form-item>
                    <LoginFormTitle class="w-full" />
                  </el-form-item>
                </el-col>
                <el-col :span="24" class="px-10px">
                  <el-form-item prop="loginName">
                    <el-input
                      v-model="loginData.loginForm.loginName"
                      :placeholder="t('login.usernamePlaceholder')"
                      :prefix-icon="iconAvatar"
                      autocomplete="off"
                    />
                  </el-form-item>
                </el-col>
                <el-col :sm="24" class="px-10px">
                  <el-form-item prop="password">
                    <el-input
                      v-model="loginData.loginForm.password"
                      :placeholder="t('login.passwordPlaceholder')"
                      :prefix-icon="iconLock"
                      type="password"
                      :show-password="false"
                      autocomplete="off"
                      @keyup.enter="handlePasswdLogin"
                    />
                  </el-form-item>
                </el-col>
                <el-col :span="24" class="px-10px" v-if="loginData.captchaEnable">
                  <el-form-item prop="captcha">
                    <el-input
                      v-model="loginData.loginForm.captcha"
                      autocomplete="off"
                      :placeholder="t('login.codePlaceholder')"
                      :prefix-icon="iconCaptcha"
                      maxlength="4"
                      class="captcha-input"
                      @focus="handleCaptchaFocus"
                      @keyup.enter="handlePasswdLogin"
                    >
                      <template #append>
                        <el-image
                          :src="loginData.captchaUrl"
                          @click="getCaptcha"
                          class="w-104px h-39px -mt-1px cursor-pointer"
                        >
                          <template #error>
                            <div class="px-6">点击刷新</div>
                          </template>
                        </el-image>
                      </template>
                    </el-input>
                  </el-form-item>
                </el-col>
                <el-col :span="24" class="px-10px -my-20px">
                  <el-form-item>
                    <el-row justify="space-between" class="w-full">
                      <el-col :span="6">
                        <el-checkbox v-model="loginData.loginForm.rememberMe">
                          {{ t('login.remember') }}
                        </el-checkbox>
                      </el-col>
                      <el-col :span="18">
                        <el-link
                          class="float-right"
                          type="primary"
                          @click="setLoginState(LoginStateEnum.RESET_PASSWD)"
                        >
                          {{ t('login.forgetPassword') }}
                        </el-link>
                      </el-col>
                    </el-row>
                  </el-form-item>
                </el-col>
                <el-col :span="24" class="px-10px">
                  <el-form-item>
                    <XButton
                      :loading="loginLoading"
                      :title="t('login.login')"
                      class="w-full"
                      type="primary"
                      @click="handlePasswdLogin"
                    />
                  </el-form-item>
                </el-col>
              </el-row>
            </ElForm>
            <ResetPasswdForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white)" />
          </div>
        </Transition>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ElLoading } from 'element-plus'

import { useDesign } from '@/hooks/web/useDesign'
import { useIcon } from '@/hooks/web/useIcon'
import { useAppStore } from '@/stores/modules/app'

import * as LoginApi from '@/api/base/login'
import * as authUtil from '@/utils/auth'
import { ThemeSwitch } from '@/layout/components/ThemeSwitch'
import { LocaleDropdown } from '@/layout/components/LocaleDropdown'
import LoginFormTitle from './components/LoginFormTitle.vue'
import ResetPasswdForm from './components/ResetPasswdForm.vue'
import { LoginStateEnum, useLoginState } from './components/useLogin'

defineOptions({ name: 'SocialLogin' })

const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const route = useRoute()

const appStore = useAppStore()
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('login')
const iconAvatar = useIcon({ icon: 'ep:avatar' })
const iconLock = useIcon({ icon: 'ep:lock' })
const iconCaptcha = useIcon({ icon: 'hugeicons:security-validation' })
const loginFormRef = ref<any>()
const { getLoginState, setLoginState } = useLoginState()
const { replace } = useRouter()
const loginLoading = ref(false)
const loginDisabled = ref(true)

const getShow = computed(() => unref(getLoginState) === LoginStateEnum.PASSWD_LOGIN)

const loginRules = {
  loginName: [required],
  password: [required],
  captcha: [required]
}

const loginData = reactive({
  isShowPassword: false,
  captchaEnable: true,
  captchaUrl: '',
  loginForm: {
    loginName: import.meta.env.VITE_APP_DEFAULT_LOGIN_LOGINNAME || '',
    password: import.meta.env.VITE_APP_DEFAULT_LOGIN_PASSWORD || '',
    captcha: '',
    captchaId: '',
    rememberMe: false
  }
})

const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE === 'true'

// tricky: 配合LoginForm.vue中redirectUri需要对参数进行encode，需要在回调后进行decode
function getUrlValue(key: string): string {
  const url = new URL(decodeURIComponent(location.href))
  return url.searchParams.get(key) ?? ''
}

const trySocialLogin = async () => {
  try {
    loginDisabled.value = true
    const type = getUrlValue('type') as any
    const redirect = getUrlValue('redirect')
    const code = route?.query?.code as string
    const state = route?.query?.state as string
    const res = (await LoginApi.socialLogin({ type, code, state })) as any
    if (res.code === '23020020') {
      message.notifyWarning('未绑定账号，需要登录绑定')
      loginDisabled.value = false
      return
    }
    authUtil.setToken(res.data)
    replace({ path: redirect || '/' })
  } catch (e) {
    // do nothing
  }
}

let loadingInstance: Closable
const handlePasswdLogin = async () => {
  loginLoading.value = true
  try {
    if (await formValidate(loginFormRef)) {
      return
    }
    const type = getUrlValue('type') as any
    const redirect = getUrlValue('redirect')
    const code = route?.query?.code as string
    const state = route?.query?.state as string

    const loginForm = {
      ...loginData.loginForm,
      socialType: type,
      socialCode: code,
      socialState: state
    }
    const res = await LoginApi.passwdLogin(loginForm)
    if (!res) {
      return
    }
    loadingInstance = ElLoading.service({
      lock: true,
      text: `${t('common.systemLoading')}...`,
      background: 'rgba(0, 0, 0, 0.7)'
    })
    if (loginForm.rememberMe) {
      const { loginName, password, rememberMe } = loginForm
      authUtil.setLoginForm({ loginName, password, rememberMe })
    } else {
      authUtil.removeLoginForm()
    }
    authUtil.setToken(res)
    replace({ path: redirect || '/' })
  } catch (e) {
    if (loginData.captchaEnable) {
      getCaptcha()
    }
  } finally {
    loginLoading.value = false
    loadingInstance?.close()
  }
}

let lastLoadCaptTime = new Date().getTime()
const getCaptcha = () => {
  // 刷新图形验证码
  lastLoadCaptTime = new Date().getTime()
  LoginApi.getCaptcha('staff_auth').then((res) => {
    loginData.captchaEnable = res.captchaEnabled ?? true
    if (loginData.captchaEnable) {
      loginData.captchaUrl = res.captchaBase64
      loginData.loginForm.captchaId = res.captchaId
    }
  })
}

const handleCaptchaFocus = () => {
  // 验证码聚焦时，若验证码已过期，则自动刷新
  if (new Date().getTime() - lastLoadCaptTime > 2 * 60 * 1000) {
    getCaptcha()
  }
}

const getLoginFormCache = () => {
  const loginForm = authUtil.getLoginForm()
  if (loginForm) {
    loginData.loginForm = {
      ...loginData.loginForm,
      loginName: loginForm.loginName ? loginForm.loginName : loginData.loginForm.loginName,
      password: loginForm.password ? loginForm.password : loginData.loginForm.password,
      rememberMe: loginForm.rememberMe
    }
  }
}

const getTenantByWebsite = async () => {
  // 根据域名获取租户信息
  if (tenantEnable) {
    // 根据域名定位tenantId
    const data = await LoginApi.getTenantByWebsite(location.host)
    if (data) {
      authUtil.setTenantId(data.id)
    }
  }
}

onBeforeMount(() => {
  trySocialLogin()
  getLoginFormCache()
  getCaptcha()
})

onMounted( () => {
  getTenantByWebsite()
})
</script>

<style scoped lang="scss">
$prefix-cls: #{$namespace}-login;

.#{$prefix-cls} {
  overflow: auto;

  &__left {
    &::before {
      position: absolute;
      top: 0;
      left: 0;
      z-index: -1;
      width: 100%;
      height: 100%;
      background-image: url('@/assets/svgs/login-bg.svg');
      background-position: center;
      background-repeat: no-repeat;
      content: '';
    }
  }
}

.captcha-input {
  :deep(.el-input-group__append) {
    padding-right: 0;
    padding-left: 0;
  }
}
</style>
